﻿/*
SINACOR - BMF&Bovespa
Arquivo: AlocacaoDireta.cs
Criado em: 14-mai-2010 17:57:02
Arquiteto Responsável: p-dmartinelli
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using Sinacor.Infra.Common;
using Sinacor.Infra.UI.Common;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.UI.Bovespa.Alocacao.Model.Parameter;
using Sinacor.Infra.Service.Security.Authorization;
using Sinacor.Infra.UI.Authorization;
using Sinacor.Infra.Common.Serialization;
using System.Collections.ObjectModel;


namespace Sinacor.UI.Bovespa.Alocacao.Presenter 
{
	public class AlocacaoDireta : AlocacaoBase<IAlocacaoDireta> 
	{
		#region Atributos
		private Communication.AlocacaoDireta _communicationAlocacaoDireta;
        private Communication.Negocio _communicationNegocio;
		private ModelCollection<Model.NegocioAlocadoDireto> _listaAlocados;
		private ModelCollection<Model.NegocioAlocadoDireto> _listaAlocadosOriginal;
		private ModelCollection<Model.Bolsa> _listaBolsas;
		private ModelCollection<Model.DadosAlocacao> _listaDigitacao;
		private ModelCollection<Model.Negocio> _listaDisponiveis;
        private Model.Parameter.FiltroNegocio _filtroNegocio;
        private ObservableCollection<EnumWrapper<Model.Enum.TipoLiquidacao>> _listaTiposLiquidacao;
        private decimal? _quantidadeEspecificar;
		#endregion
		#region Propriedades

        public ObservableCollection<EnumWrapper<Model.Enum.TipoLiquidacao>> ListaTiposLiquidacao
        {
            get
            {
                return _listaTiposLiquidacao;
            }
            set
            {
                _listaTiposLiquidacao = value;
            }
        }

        public Model.Parameter.FiltroNegocio Filtro
        {
            get { return _filtroNegocio; }
            set { _filtroNegocio = value; }
        }

		/// <summary>
		/// Lista de negocios alocados pra bind com a grid
		/// </summary>
		public ModelCollection<Model.NegocioAlocadoDireto> ListaAlocados
		{
			get { return _listaAlocados; }
			set { _listaAlocados = value; }
		}

		/// <summary>
		/// Copia da lista de negocios alocados original (sem filtro) não fazer bind
		/// </summary>
		public ModelCollection<Model.NegocioAlocadoDireto> ListaAlocadosOriginal
		{
			get { return _listaAlocadosOriginal; }
			set { _listaAlocadosOriginal = value; }
		}

		public ModelCollection<Model.Bolsa> ListaBolsas
		{
			get { return _listaBolsas; }
			set { _listaBolsas = value; }
		}

		public ModelCollection<Model.DadosAlocacao> ListaDigitacao
		{
			get { return _listaDigitacao; }
			set 
            { 
                _listaDigitacao = value;
                ListaDigitacao.EnableStateControl = true;
            }
		}

		public ModelCollection<Model.Negocio> ListaDisponiveis
		{
			get { return _listaDisponiveis; }
			set { _listaDisponiveis = value; }
		}

        public decimal? QuantidadeEspecificar
        {
            get { return _quantidadeEspecificar; }
            set { _quantidadeEspecificar = value; }
        }
		#endregion
        #region Construtores

        public AlocacaoDireta(IAlocacaoDireta view)
            : base(view)
        {
            this.ListaTiposLiquidacao = EnumWrapper<Model.Enum.TipoLiquidacao>.GetEnums(Model.Enum.TipoLiquidacao.Custodiante, Model.Enum.TipoLiquidacao.Normal);
        }

        #endregion
		#region Métodos
		/// <summary>
		/// Calcula o saldo do negocio informado
		/// </summary>
		/// <param name="negocio"></param>
		public decimal CalcularSaldo(Model.Negocio negocio)
		{
            decimal? saldo = negocio.Quantidade - negocio.QuantidadeCasada;

            if(ListaDigitacao.Count > 0)
            {
                decimal? total = (from v in this.ListaDigitacao
                                 select v.QuantidadeEspecificar).Sum();
                saldo = saldo - total;
            }
            return saldo.Value;
			
		}

		/// <summary>
		/// Consultar as bolsas
		/// </summary>
		public void ConsultarBolsas()
		{
            if (_communicationNegocio == null)
                _communicationNegocio = new Sinacor.UI.Bovespa.Alocacao.Communication.Negocio(this.Session);
            _listaBolsas = _communicationNegocio.ConsultarBolsas();
		}

		/// <summary>
		/// Busca os negocios alocados e os disponiveis
		/// </summary>
		public void ConsultarNegocios()
		{
            _listaAlocados = _communicationAlocacaoDireta.ConsultarNegociosAlocados(_filtroNegocio);
            _listaAlocadosOriginal = (ModelCollection<Model.NegocioAlocadoDireto>)CloneHelper.Clone(_listaAlocados);	

            View.AtualizarListaAlocados();

            _listaDisponiveis = _communicationAlocacaoDireta.ConsultarNegociosDisponiveis(_filtroNegocio);

            View.AtualizarListaDisponiveis();

            if (_listaAlocados.Count == 0 && _listaDisponiveis.Count == 0)
            {
                View.InformarRegistroNaoEncontrado();
            }
		}

        public Model.Direcionado ObterDirecionado(Model.DadosAlocacao digitacao, Model.Negocio disponivel)
        {
            var direto = new Model.NegocioAlocadoDireto
            {
                DadosAlocacao = digitacao,
                Negocio = disponivel
            };

            return _communicationAlocacaoDireta.ObterDirecionado(direto);
        }

		/// <summary>
		/// Desaloca varios negocios
		/// </summary>
		/// <param name="negocios"></param>
		public bool ExcluirNegocioAlocado(ModelCollection<Model.NegocioAlocadoDireto> negocios)
		{
            _communicationAlocacaoDireta.ExcluirNegocioAlocado(negocios);

            ConsultarNegocios();
            View.InformarCancelamentoRealizado();

            return true;
		}

		/// <summary>
		/// Filtra a grid dos negocios alocados pelo codigo do négocio
		/// </summary>
		/// <param name="negociosSelecionados"></param>
		public void FiltrarAlocados(ModelCollection<Model.Negocio> negociosSelecionados)
		{
			
            if (negociosSelecionados.Count == 1)
            {
                IQueryable Retorno;
                IQueryable<Model.NegocioAlocadoDireto> _eventosFiltrados = ListaAlocadosOriginal.AsQueryable();
                ListaAlocados = new ModelCollection<Sinacor.UI.Bovespa.Alocacao.Model.NegocioAlocadoDireto>();
                Retorno = from v in _eventosFiltrados where v.Negocio.Codigo == negociosSelecionados[0].Codigo select v;
                foreach (Model.NegocioAlocadoDireto item in Retorno)
                {
                    this.ListaAlocados.Add(item);
                }                
            }
            else
            {
                ListaAlocados = ListaAlocadosOriginal;
            }
            View.AtualizarListaAlocados();
			
		}
        
        
		/// <summary>
		/// Inicializa os combos
		/// </summary>
		public void Inicializar()
		{
            _communicationAlocacaoDireta = new Sinacor.UI.Bovespa.Alocacao.Communication.AlocacaoDireta(this.Session);
            _filtroNegocio = new FiltroNegocio();
            
            var communicationMovimentoBolsa = new Sinacor.UI.Bovespa.Alocacao.Communication.ControleMovimentoBolsa(this.Session);
            Model.InformacoesMovimento movimento = communicationMovimentoBolsa.ObterInformacoesMovimento(new Model.DataMovimento());

            if (movimento.EstadoMovimento == Sinacor.UI.Bovespa.Alocacao.Model.Enum.TipoMovimento.Abertura)
            {
                if ((new Sinacor.UI.Bovespa.Alocacao.Communication.Acesso(this.Session)).VerificarSistemaInstalado("ORD"))
                {
                    var communicationMovimentoOrdens = new Sinacor.UI.Bovespa.Alocacao.Communication.ControleMovimentoOrdens(this.Session);
                    movimento = communicationMovimentoOrdens.ObterInformacoesMovimento(new Model.DataMovimento());

                    if (movimento.EstadoMovimento != Sinacor.UI.Bovespa.Alocacao.Model.Enum.TipoMovimento.Abertura)
                    {
                        View.BloquearDigitacao();
                        View.InformarUsuarioSemPermissao();
                        InicializarFiltros();
                        return;
                    }
                }
                
                if (AuthorizationManager.GetInstance().CheckUserAccess("BOL", "BCLRAP"))
                {
                    if (!AuthorizationManager.GetInstance().CheckUserAccess("BOL", "ARED"))
                        View.BloquearColunaPercRedAcr();
                }
                else
                {
                    View.BloquearDigitacao();
                    View.InformarUsuarioSemPermissao();
                }
            }
            else
            {
                View.BloquearDigitacao();
                View.InformarUsuarioSemPermissao();
            }

            InicializarFiltros();
		}

        private void InicializarFiltros()
        {
            ConsultarCalendarios();
            View.AtualizarListaCalendarios();
            ConsultarBolsas();
            View.AtualizarListaBolsas();
            View.DefinirFiltroPadrao();
        }

		/// <summary>
		/// Executa logica da tela quando a digitacao é iniciada
		/// </summary>
		/// <param name="negociosSelecionados"></param>
		public void IniciarDigitacao(ModelCollection<Model.Negocio> negociosSelecionados)
		{
            QuantidadeEspecificar = null;

            if (negociosSelecionados != null && negociosSelecionados.Count > 0)
            {
                if (negociosSelecionados.Count > 1)
                {
                    View.BloquearNovaLinhaDigitacao();
                    View.BloquearColunaQuantidade();
                }
                else
                {
                    QuantidadeEspecificar = CalcularSaldo(negociosSelecionados[0]);
                }
                int quantidadeMercadosDerivativos = (from v in negociosSelecionados where v.Mercado != Model.Enum.TipoMercado.Vista && v.Mercado != Model.Enum.TipoMercado.Fracionario && v.Mercado != Model.Enum.TipoMercado.Futuro select v).Count<Model.Negocio>();

                if (quantidadeMercadosDerivativos > 0)
                    View.BloquearColunasDirecionado();
                else
                    View.DesbloquearColunasDirecionado();
            }
            else
                View.CancelarDigitacao();
		}

		/// <summary>
		/// Utilizado para limpar os campos de filtro
		/// </summary>
		public void LimparFiltro()
		{
            View.DefinirFiltroPadrao();
		}

		/// <summary>
		/// Monta os objetos de alocacao e salva a digitacao
		/// </summary>
		/// <param name="digitacao"></param>
		/// <param name="disponivel"></param>
		public bool SalvarDigitacao(ModelCollection<Model.DadosAlocacao> digitacao, ModelCollection<Model.Negocio> disponivel)
		{
            
			ModelCollection<Model.NegocioAlocadoDireto> negociosAlocadosDireto = new ModelCollection<Model.NegocioAlocadoDireto>();
            if (disponivel.Count > 1)
            {
                for (int i = 0; i < disponivel.Count; i++)
                {
                    var dadosAlocacao = (Model.DadosAlocacao)CloneHelper.Clone(digitacao[0]);
                    dadosAlocacao.QuantidadeEspecificar = disponivel[i].Saldo.Value;

                    var direto = new Model.NegocioAlocadoDireto
                    {
                        DadosAlocacao = dadosAlocacao,
                        Negocio = disponivel[i]
                    };
                    negociosAlocadosDireto.Add(direto);
                }
            }
            else
            {
                for (int i = 0; i < digitacao.Count; i++)
                {
                    var direto = new Model.NegocioAlocadoDireto
                    {
                      DadosAlocacao = digitacao[i],
                      Negocio = disponivel[0]
                    };
                    negociosAlocadosDireto.Add(direto);

                }
            }

            try
            {
                _communicationAlocacaoDireta.AlocarNegocioDisponivel(negociosAlocadosDireto);
                ListaDigitacao = new ModelCollection<Sinacor.UI.Bovespa.Alocacao.Model.DadosAlocacao>();
                View.InformarAlocacaoGravada();
                View.AtualizarListaDigitacao();
                ConsultarNegocios();
                return true;
            }
            catch (Exception ex)
            {
                base.HandleException(ex);
                return false;
            }
		}

		#endregion
	}

}